﻿/**********************************************************
 ●项目：Smartkernel
 ●公司：智能核心信息技术研发中心
 ●作者：曹艳白
 ●邮箱：caoyanbai@gmail.com
 ●创建：2008-08-10
**********************************************************/
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Xml;
using System.Management;
using Smartkernel.Security.Cryptography;

namespace Smartkernel.IO
{
    /// <summary>
    /// 智能文件：文件以及文件夹操作的智能封装
    /// </summary>
    public static partial class SmartFile
    {
        #region 读写操作
        /// <summary>
        /// 写入文本文件内容：不自动换行
        /// </summary>
        /// <param name="filePath">文件路径，文件不存在时会自动创建，存在时则追加信息</param>
        /// <param name="message">写入内容</param>
        public static void WriteText(string filePath, string message)
        {
            WriteText(filePath, message, false, Encoding.Default);
        }
        /// <summary>
        /// 写入文本文件内容：不自动换行
        /// </summary>
        /// <param name="filePath">文件路径，文件不存在时会自动创建，存在时则追加信息</param>
        /// <param name="message">写入内容</param>
        /// <param name="encoding">编码方式</param>
        public static void WriteText(string filePath, string message, Encoding encoding)
        {
            WriteText(filePath, message, false, encoding);
        }
        /// <summary>
        /// 写入文本文件内容：自动换行
        /// </summary>
        /// <param name="filePath">文件路径，文件不存在时会自动创建，存在时则追加信息</param>
        /// <param name="message">写入内容</param>
        public static void WriteLineText(string filePath, string message)
        {
            WriteText(filePath, message, true, Encoding.Default);
        }
        /// <summary>
        /// 写入文本文件内容：自动换行
        /// </summary>
        /// <param name="filePath">文件路径，文件不存在时会自动创建，存在时则追加信息</param>
        /// <param name="message">写入内容</param>
        /// <param name="encoding">编码方式</param>
        public static void WriteLineText(string filePath, string message, Encoding encoding)
        {
            WriteText(filePath, message, true, encoding);
        }
        /// <summary>
        /// 内部方法：Write和WriteLine的实际功能
        /// </summary>
        /// <param name="filePath">文件路径，文件不存在时会自动创建，存在时则追加信息</param>
        /// <param name="message">写入内容</param>
        /// <param name="isAutoNewline">是否自动换行</param>
        private static void WriteText(string filePath, string message, bool isAutoNewline)
        {
            WriteText(filePath, message, isAutoNewline, Encoding.Default);
        }
        /// <summary>
        /// 内部方法：Write和WriteLine的实际功能
        /// </summary>
        /// <param name="filePath">文件路径，文件不存在时会自动创建，存在时则追加信息</param>
        /// <param name="message">写入内容</param>
        /// <param name="isAutoNewline">是否自动换行</param>
        /// <param name="encoding">编码方式</param>
        private static void WriteText(string filePath, string message, bool isAutoNewline, Encoding encoding)
        {
            using (StreamWriter streamWriter = new StreamWriter(filePath, true, encoding))
            {
                if (isAutoNewline)
                {
                    streamWriter.WriteLine(message);
                }
                else
                {
                    streamWriter.Write(message);
                }
                streamWriter.Flush();
            }
        }
         /// <summary>
        /// 读取文本文件的内容
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <returns>内容</returns>
        public static string ReadText(string filePath)
        {
            return ReadText(filePath, Encoding.Default);
        }
        /// <summary>
        /// 读取文本文件的内容
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="encoding">编码方式</param>
        /// <returns>内容</returns>
        public static string ReadText(string filePath, Encoding encoding)
        {
            string content = string.Empty;
            using (StreamReader streamReader = new StreamReader(filePath, encoding))
            {
                content = streamReader.ReadToEnd();
            }
            return content;
        }
        #endregion
    }
    public static partial class SmartFile
    {
        #region 分割操作
        /// <summary>
        /// 拆分文件
        /// </summary>
        /// <param name="sourceFilePath">源文件路径</param>
        /// <param name="targetFilePath">目标文件路径</param>
        /// <param name="quantity">数量</param>
        public static void Split(string sourceFilePath, string targetFilePath, int quantity)
        {
            using (FileStream sourceFileStream = new FileStream(sourceFilePath, FileMode.Open, FileAccess.Read))
            {
                long fileSize = Convert.ToInt64(Math.Ceiling(Convert.ToDouble(sourceFileStream.Length) / Convert.ToDouble(quantity)));
                for (int i = 0; i < quantity; i++)
                {
                    using (FileStream targetFileStream = new FileStream((targetFilePath + "_" + i + "_.part"), FileMode.OpenOrCreate, FileAccess.Write))
                    {
                        long count = 0;
                        byte[] buffer = new byte[fileSize];
                        count = sourceFileStream.Read(buffer, 0, Convert.ToInt32(fileSize));
                        if (count > 0)
                        {
                            targetFileStream.Write(buffer, 0, Convert.ToInt32(count));
                        }
                    }
                }
            }
        }
        /// <summary>
        /// 合并文件
        /// </summary>
        /// <param name="sourceFilePath">源文件路径</param>
        /// <param name="targetFilePath">目标文件路径</param>
        /// <param name="quantity">数量</param>
        public static void Unite(string sourceFilePath, string targetFilePath, int quantity)
        {
            using (FileStream targetFileStream = new FileStream(targetFilePath, FileMode.OpenOrCreate, FileAccess.Write))
            {
                for (int i = 0; i < quantity; i++)
                {
                    using (FileStream sourceFileStream = new FileStream((sourceFilePath + "_" + i + "_.part"), FileMode.OpenOrCreate, FileAccess.Read))
                    {
                        long count = 0;
                        byte[] buffer = new byte[1024];
                        while ((count = sourceFileStream.Read(buffer, 0, 1024)) > 0)
                        {
                            targetFileStream.Write(buffer, 0, Convert.ToInt32(count));
                        }
                    }
                }
            }
        }
        #endregion
    }
    public static partial class SmartFile
    {
        #region 其它操作
        /// <summary>
        /// 在一个文件夹内递归查找文件，判断文件是否存在
        /// </summary>
        /// <param name="fileName">待查找的文件名，必须有扩展名</param>
        /// <param name="folderPath">查找范围的文件夹</param>
        /// <param name="searchOption">搜索的范围，是不是包含子目录</param>
        /// <param name="filePathList">找到的文件的路径</param>
        /// <returns>是否存在</returns>
        public static bool Exists(string fileName, string folderPath, SearchOption searchOption, out List<string> filePathList)
        {
            filePathList = new List<string>(Directory.GetFiles(folderPath, fileName, searchOption));

            return filePathList.Count > 0;
        }
        /// <summary>
        /// 在一个文件夹内递归查找文件，判断文件是否存在
        /// </summary>
        /// <param name="fileName">待查找的文件名</param>
        /// <param name="folderPath">查找范围的文件夹</param>
        /// <param name="searchOption">搜索的范围，是不是包含子目录</param>
        /// <returns>是否存在</returns>
        public static bool Exists(string fileName, string folderPath, SearchOption searchOption)
        {
            List<string> filePathList;
            return Exists(fileName, folderPath, searchOption, out filePathList);
        }
        /// <summary>
        /// 通过文件的字节数获得文件的易理解大小，如1.5GB
        /// </summary>
        /// <param name="fileSize">字节大小</param>
        /// <returns>文件大小的易理解形式</returns>
        public static string FileSize(long fileSize)
        {
            string result = string.Empty;
            if (fileSize == 0)
            {
                result = "0 B";
            }
            else if (fileSize > 0 && fileSize < 1024)
            {
                result = fileSize.ToString() + " B";
            }
            else if (fileSize >= 1024 && fileSize < 1024000)
            {
                result = Math.Round(System.Convert.ToDouble(fileSize / 1024.00), 2) + " KB";
            }
            else if (fileSize >= 1024000 && fileSize < 1024000000)
            {
                result = Math.Round(System.Convert.ToDouble(fileSize / 1024.00 / 1024.00), 2) + " MB";
            }
            else if (fileSize >= 1024000000)
            {
                result = Math.Round(System.Convert.ToDouble(fileSize / 1024.00 / 1024.00 / 1024.00), 2) + " GB";
            }
            return result;
        }
        /// <summary>
        /// 获得C#项目所包含文件的列表
        /// </summary>
        /// <param name="projectFilePath">项目文件路径（.csproj文件）</param>
        /// <returns>文件列表</returns>
        public static List<string> GetProjectFileList(string projectFilePath)
        {
            List<string> list = new List<string>();

            SelectNodes(list, "//ab:ItemGroup//ab:Content", projectFilePath);

            SelectNodes(list, "//ab:ItemGroup//ab:Compile", projectFilePath);

            SelectNodes(list, "//ab:ItemGroup//ab:EmbeddedResource", projectFilePath);

            SelectNodes(list, "//ab:ItemGroup//ab:None", projectFilePath);

            return list;
        }
        /// <summary>
        /// 获得指定文件夹下的文件扩展名类型
        /// </summary>
        /// <param name="directoryPath">文件夹路径</param>
        /// <param name="searchOption">搜索的范围，是不是包含子目录</param>
        /// <returns>查找的结果</returns>
        public static List<string> GetExtensionsType(string directoryPath, SearchOption searchOption)
        {
            var linq = from file in Directory.GetFiles(directoryPath, "*.*", searchOption) select Path.GetExtension(file);
            return linq.Distinct().ToList<string>();
        }
        /// <summary>
        /// 获得指定文件夹下的文件列表
        /// </summary>
        /// <param name="directoryPath">文件夹路径</param>
        /// <param name="searchOption">搜索的范围，是不是包含子目录</param>
        /// <returns>查找的结果</returns>
        public static List<string> GetFiles(string directoryPath, SearchOption searchOption)
        {
            var linq = from file in Directory.GetFiles(directoryPath, "*.*", searchOption) select file;
            return linq.ToList<string>();
        }
        private static void SelectNodes(List<string> list, string filter, string projectFilePath)
        {
            XmlDocument xmlDocument = new XmlDocument();
            xmlDocument.Load(projectFilePath);
            XmlNamespaceManager xmlNamespaceManager = new XmlNamespaceManager(xmlDocument.NameTable);
            xmlNamespaceManager.AddNamespace("ab", "http://schemas.microsoft.com/developer/msbuild/2003");

            XmlNodeList xmlNodeList = xmlDocument.SelectNodes(filter, xmlNamespaceManager);
            foreach (XmlNode xmlNode in xmlNodeList)
            {
                string fileName = xmlNode.Attributes["Include"].Value;
                if (!list.Contains(fileName))
                {
                    list.Add(fileName);
                }
            }
        }
        /// <summary>
        /// 复制文件夹
        /// </summary>
        /// <param name="source">源文件夹</param>
        /// <param name="target">目标文件夹</param>
        /// <param name="overWriteFiles">是否覆盖文件</param>
        public static void CopyFolder(string source, string target, bool overWriteFiles)
        {
            Scripting.FileSystemObjectClass fso = new Scripting.FileSystemObjectClass();
            fso.CopyFolder(source, target, overWriteFiles);
        }
        /// <summary>
        /// 修改文件名称
        /// </summary>
        /// <param name="filePath">文件路径</param>
        /// <param name="newName">新的文件名</param>
        /// <param name="overWriteFile">是否覆盖文件</param>
        public static void ChangeName(string filePath, string newName, bool overWriteFile)
        {
            File.Copy(filePath, Path.GetDirectoryName(filePath).TrimEnd('\\') + @"\" + newName, overWriteFile);
            File.Delete(filePath);
        }
        /// <summary>
        /// 计算指定文件夹的总大小，包含所有子目录中的文件
        /// </summary>
        /// <param name="folderPath">文件夹的路径</param>
        /// <returns>总大小</returns>
        public static long GetFolderTotalSize(string folderPath)
        {
            long size = 0;
            DirectoryInfo directory = new DirectoryInfo(folderPath);
            FileInfo[] files = directory.GetFiles();
            foreach (FileInfo file in files)
            {
                size += file.Length;
            }
            DirectoryInfo[] subDirectories = directory.GetDirectories();
            foreach (DirectoryInfo subDirectory in subDirectories)
            {
                size += GetFolderTotalSize(subDirectory.FullName);
            }
            return size;
        }
        /// <summary>
        /// 比较两个文件是否相同，根据哈希码进行比较的方式
        /// </summary>
        /// <param name="path1">文件路径1</param>
        /// <param name="path2">文件路径2</param>
        /// <returns>比较的结果</returns>
        public static bool Compare(string path1, string path2)
        {
            return SmartHashPassword.FileHashPassword(path1) == SmartHashPassword.FileHashPassword(path2);
        }
        /// <summary>
        /// 设置指定目录为共享目录
        /// </summary>
        /// <param name="folderPath">目录路径</param>
        /// <param name="shareName">共享名称</param>
        public static void SetShareFolder(string folderPath, string shareName)
        {
            ManagementClass mc = new ManagementClass(new ManagementPath("Win32_Share"));
            object[] args = { folderPath, shareName, "0", "10", shareName, "" };
            mc.InvokeMethod("create", args);
        }
        #endregion
    }
}
